Skip to content

fix(self-hosting): pass CAP_CHROME_EXTENSION_ID through to the web container (#1993)#2035

Closed
DPS0340 wants to merge 1 commit into
CapSoftware:mainfrom
DPS0340:fix/self-host-chrome-extension-id
Closed

fix(self-hosting): pass CAP_CHROME_EXTENSION_ID through to the web container (#1993)#2035
DPS0340 wants to merge 1 commit into
CapSoftware:mainfrom
DPS0340:fix/self-host-chrome-extension-id

Conversation

@DPS0340

@DPS0340 DPS0340 commented Jul 25, 2026

Copy link
Copy Markdown

Fixes #1993.

Problem

CAP_CHROME_EXTENSION_ID is declared in the env schema (packages/env/server.ts:82) and is load-bearing for extension login, but it is not mapped into the cap-web service in either compose file. Self-hosters have no supported way to set it, so extension login always fails.

The failure is not a soft one. validateExtensionRedirectUri (packages/web-backend/src/Extension/Http.ts) only tolerates an unpinned extension id on localhost:

const configuredExtensionId = serverEnv().CAP_CHROME_EXTENSION_ID;

if (configuredExtensionId) {
  if (extensionId !== configuredExtensionId) return yield* new HttpApiError.BadRequest();
  return url;
}

// ...localhost-only fallback
const isLocalDevelopment =
  serverEnv().NODE_ENV !== "production" &&
  (webHostname === "localhost" || webHostname === "127.0.0.1");

if (!isLocalDevelopment) return yield* new HttpApiError.BadRequest();

That check is correct and I have deliberately not touched it — the comment above it explains why, and it's right: without a pinned id, any installed extension could mint auth keys for a signed-in user. The bug is purely that a self-hosted deployment has no way to satisfy it, so every redirect URI is rejected with the 400 the reporter saw.

Fix

Three mechanical additions, no logic changes:

  • docker-compose.yml — pass CAP_CHROME_EXTENSION_ID: ${CAP_CHROME_EXTENSION_ID:-} to cap-web, matching how the other optional integrations (GOOGLE_CLIENT_ID, APPLE_CLIENT_SECRET, RESEND_API_KEY) are wired.
  • docker-compose.coolify.yml — same.
  • docker-compose.coolify.env.example — a documented, empty entry so it's discoverable.

Plus a Chrome Extension section in self-hosting.mdx, next to the existing Google/Apple OAuth sections, explaining what the value is, why it's required, and where to find it.

Defaulting to empty (:-) keeps the current behaviour for anyone not using the extension: the var stays unset, the schema treats it as optional(), and nothing changes.

Notes

I left docker-compose.template.yml alone — it's a minimal template that doesn't carry the OAuth or Resend vars either, so adding just this one would be inconsistent with its scope.

Verification

  • Both compose files parse as valid YAML after the change, and the key resolves as expected:
    docker-compose.yml:          present=True value='${CAP_CHROME_EXTENSION_ID:-}'
    docker-compose.coolify.yml:  present=True value='${CAP_CHROME_EXTENSION_ID:-}'
    
  • No application code touched, so no type or lint surface is affected.

Diff: 4 files, +29/-0.

…ntainer

The extension auth endpoint requires a pinned extension id on any reachable
deployment — without one it rejects every redirect URI, since an unpinned id
would let any installed extension mint auth keys for a signed-in user.

The variable existed in the env schema but was never mapped into cap-web in
either compose file, so self-hosters had no supported way to set it and
extension login always failed with a 400. Document it alongside the other
optional integrations.
@DPS0340

DPS0340 commented Jul 25, 2026

Copy link
Copy Markdown
Author

@tembo please review

@DPS0340

DPS0340 commented Jul 25, 2026

Copy link
Copy Markdown
Author

Heads-up on CI: the Test Self-Hosting and CI workflows are sitting in action_required on this PR — GitHub gates workflow runs on first-time contributors until a maintainer approves them. So the checks you see green here are only the ones that don't need approval (Socket, Superagent, Contributor trust).

That matters more than usual for this change, because test-self-hosting.yml triggers specifically on docker-compose.yml and docker-compose.coolify.yml — exactly the files touched. It brings the whole stack up with docker compose up -d and waits for MySQL/MinIO health, so approving the run is a genuine end-to-end check that this doesn't break the self-host path, not a formality.

I verified locally what I could — both files parse as valid YAML and the key resolves to '${CAP_CHROME_EXTENSION_ID:-}' — but I can't run the compose stack here, so the workflow approval is the real verification.

(The red Vercel check is the usual fork-PR deploy-token issue, not related.)

@DPS0340

DPS0340 commented Jul 26, 2026

Copy link
Copy Markdown
Author

@tembo please review

@DPS0340

DPS0340 commented Jul 26, 2026

Copy link
Copy Markdown
Author

@richiemcilroy#1992 by @jerryno6 already does this, 16 days before mine. Please take theirs.

The core addition is byte-identical:

+      CAP_CHROME_EXTENSION_ID: ${CAP_CHROME_EXTENSION_ID:-}

in both docker-compose.yml and docker-compose.coolify.yml. They also update README.md and docker-compose.coolify.env.example; I updated apps/web/content/docs/self-hosting.mdx instead. Same fix, different doc file, theirs first.

Closing in favour of #1992. If it's useful once that lands, the self-hosting.mdx paragraph is a docs-only follow-up I'm happy to send separately — but it shouldn't hold up a 16-day-old PR.

This is the fourth overlap in my batch (#2029, #2031, #2040, this). All four trace to the same skipped check, and I've now run it properly across all nine: #2030, #2032, #2034, #2036, #2038 are the ones with no functional overlap.

#2036 shares the two compose files textually — it passes AI provider keys (OPENAI_API_KEY etc.) through to the web container, which is a different variable set and a different bug — but it will conflict with #1992 on those lines, so #1992 should land first and I'll rebase.

@DPS0340

DPS0340 commented Jul 26, 2026

Copy link
Copy Markdown
Author

Closing as promised — #1992 by @jerryno6 covers this and got there first.

No action needed from anyone; I'm removing it from the review queue rather than leaving it sitting as something you'd have to diff and dismiss. Nothing here is lost: if any piece turns out to be worth having after #1992 by @jerryno6 lands, I'll send it as a small follow-up against that.

@DPS0340 DPS0340 closed this Jul 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(self-hosting): Chrome extension login fails on self-hosted instances (missing CAP_CHROME_EXTENSION_ID)

1 participant